#include "rnet.h"
#include "server_loop_task.h"
#include "server_task.h"
#include "server_service.h"
#include "app_service.h"

#include <sys/types.h>
#include <sys/wait.h>

void server_task::run()
{
	while( true )
	{
		if ( !server_service::_instance().connect() )
		{
			sleep(1);
			continue ;
		}

		read();
	}
}

bool server_task::read()
{
	while(true)
	{		
		rlog << "read server(" << m_task.mi_fd << ")" << endl ;
		if ( rnet::read( m_task.mi_fd, m_task.mv_data, 0 ) < 0 )
			goto quit;

		while(true)
		{
			if ( (int)m_task.mv_data.size() < 4 )
				return true;

			int length = 0 ;
			memcpy( (char*)&length, &m_task.mv_data[0], 4 ) ;

			if ( (int)m_task.mv_data.size() < length + 4 )
				return true;

			string s_json(m_task.mv_data.begin()+4, m_task.mv_data.begin()+4+length) ;
			m_task.m_time = time(NULL) ;	
			m_task.mv_data.erase(m_task.mv_data.begin(), m_task.mv_data.begin()+4+length) ;

			rlog << "read server(" << m_task.mi_fd << ") data" << endl << s_json << endl ;	

			if ( !parse(s_json) )
			{
				rlog << "server(" << m_task.mi_fd << ") parse() error" << endl ;
				goto quit;
			}
		}
	}

quit:
	m_task.clear();
	return false;
}

bool server_task::parse(const string& s_json )
{
	rmutex(m_task.m_lock);

	Value root ;
	Reader reader ;	

	if ( !reader.parse( s_json, root ) )
	{
		rlog << "server(" << m_task.mi_fd << ") rjson::parse() error" << endl ;
		rjson::write_failure(m_task.mi_fd, "json error" ) ;
		return false ;
	}

	if ( root.isMember( "error_reason" ) )
		return true ;

	if( root.isMember( "display_app_version" ) 
			&& root.isMember( "display_app_path" ) 
			&& !root["display_app_version"].asString().empty()
			&& !root["display_app_path"].asString().empty() )
	{
		app_service::_instance().do_display_app_update(root["display_app_version"].asString(), root["display_app_path"].asString());
		return true ;
	}

	if( root.isMember( "control_app_version" ) 
			&& root.isMember( "control_app_path" ) 
			&& !root["control_app_version"].asString().empty()
			&& !root["control_app_path"].asString().empty() )
	{
		app_service::_instance().do_control_app_update(root["control_app_version"].asString(), root["control_app_path"].asString());
		return true ;
	}
	
	if( root.isMember( "daemon_version" ) 
			&& root.isMember( "daemon_path" ) 
			&& !root["daemon_version"].asString().empty()
			&& !root["daemon_path"].asString().empty() )
	{
		do_daemon_update(root["daemon_version"].asString(), root["daemon_path"].asString());
		return true ;
	}

	rlog << "server(" << m_task.mi_fd << ") json error" << endl ;
	rjson::write_failure( m_task.mi_fd, "json error" ) ;	
	
	return false ;
}

void server_task::do_daemon_update(const string& s_new_version, const string& s_path)
{
	if ( s_new_version.empty() )
	{
		rlog << "s_new_version empty" << endl;
		return ;
	}

	if( s_path.empty() )
	{
		rlog << "s_path empty" << endl;
		return ;
	}	

	if ( compare_version( gs_daemon_version, s_new_version ) < 0  )
	{
		rmutex rlock(m_lock);
		
		if(mb_downloading)
		{
			rlog << "------------------ in downloading --------------------" << endl;
			return ;
		}

		mb_downloading = true ;

		if ( !download(s_path) )
		{
			rlog << "service_task.download(" << s_path << ") error" << endl ;
			rjson::write_failure(m_task.mi_fd, "service_task.download() error" ) ;
			mb_downloading = false ;
			return ;
		}

		mb_downloading = false ;

		while(true)
		{
			if( app_service::_instance().mb_using )
			{
				rlog << "waiting for running machine unuse status for update" << endl ;
				sleep(3) ;
			}

			rlog << "daemon quit now for update" << endl;
			exit(0);
		}
	}
}

bool server_task::download(const string& s_path )
{
	rlog << "------------------ start downloading --------------------" << endl;
	string cmd = "busybox wget -P /data/pbjd/update/ " + s_path ;
	rlog << "--------------------- 11111111111111 ----------------------" << endl;
	int status = android_system(cmd.c_str());
	rlog << "--------------------- 22222222222222222 ----------------------" << endl;
	if ( WEXITSTATUS(status) != 0 )
	{
		rlog << "android_system(" << cmd << ") error : " << endl;
		return false ;
	}
	rlog << "--------------------- download success ----------------------" << endl;

	return true ;
}

int server_task::compare_version( string s_local_version, string s_server_version )
{
	s_local_version.erase(std::remove(s_local_version.begin(), s_local_version.end(), '.'), s_local_version.end());
	s_server_version.erase(std::remove(s_server_version.begin(), s_server_version.end(), '.'), s_server_version.end());

	return ( (int)atoi(s_local_version.c_str()) - (int)atoi(s_server_version.c_str()) ) ;
}

int server_task::android_system( const string& s_commamd )
{
	pid_t	pid ;
	int	status = 0 ;

	if ( s_commamd.empty() )
	{
		rlog << "s_command empty" << endl ;
		return	-1 ;
	}

	if ( (pid=fork()) < 0 )	status = -1 ;
	else if ( pid == 0 )
	{
		rlog << "--------------------- aaaaaaaa ----------------------" << endl;
		if( execl( "/system/bin/sh", "sh", "-c", s_commamd.c_str(), (char*)0 ) == -1 )
		{
			rlog << "execl(" << s_commamd.c_str() << ") error : " << strerror(errno) << endl;
			status = errno ;
		}

		rlog << "--------------------- bbbbbbbbbbbbbb ----------------------" << endl;
		_exit(status) ;
	}
	else
	{
		rlog << "--------------------- ccccccccccccccccc ----------------------" << endl;
		while( waitpid( pid, &status, 0 ) < 0 )
		{
			if ( errno != EINTR )
			{
				status = -1 ;
				break ;
			}
		}

		rlog << "--------------------- dddddddddddddddd ----------------------" << endl;
	}

	return	status ;
}


